#include "audio.h"

#include "main.h"
#include "flash.h"

#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

extern DAC_HandleTypeDef hdac;
extern TIM_HandleTypeDef htim7;

#define AUDIO_BUFFER_SIZE 1024
struct AUDIO_STRUCT
{
	uint32_t size;
	uint32_t offset;
	uint32_t read_pos;
	uint8_t audio_data[2][AUDIO_BUFFER_SIZE];
	uint16_t play_size[2];
	uint8_t audio_flag[2];
	uint8_t now_paly_index;
	SemaphoreHandle_t xSemaphore;
};

struct AUDIO_STRUCT audio_s;

static void wave16to12(int16_t *buf, int size)
{
	for (int i = 0; i < size; i++)
	{
		//buf[i] *= 20;
		buf[i] = buf[i] + 32768;
		buf[i] = buf[i] >> 4;
	}
}

void audio_struct_init(struct AUDIO_STRUCT *as)
{
	as->audio_flag[0] = 0;
	as->audio_flag[1] = 0;
	as->play_size[0] = 0;
	as->play_size[1] = 0;
	as->read_pos = 0;
	as->size = 0;
	as->offset = 0;
	as->now_paly_index = 0;
}

static void audio_read_buffer(uint8_t isReady)
{
	uint8_t index;
	if(isReady != 0 )
	{
		index = 0;
		audio_s.now_paly_index = 0;
	}else{
		index = (audio_s.now_paly_index + 1) % 2;
	}

	if (audio_s.read_pos < audio_s.size)
	{
		
		if (audio_s.audio_flag[index] == 0)
		{
			if (audio_s.read_pos + AUDIO_BUFFER_SIZE <= audio_s.size)
			{
				SPI_Flash_Read(audio_s.audio_data[index], audio_s.offset + audio_s.read_pos, AUDIO_BUFFER_SIZE);
				audio_s.play_size[index] = AUDIO_BUFFER_SIZE;
			}
			else
			{
				SPI_Flash_Read(audio_s.audio_data[index], audio_s.offset + audio_s.read_pos, audio_s.size - audio_s.read_pos);
				audio_s.play_size[index] = audio_s.size - audio_s.read_pos;
			}

			wave16to12((int16_t *)audio_s.audio_data[index], audio_s.play_size[index] / 2);
			audio_s.audio_flag[index] = 1;
			audio_s.read_pos += audio_s.play_size[index];
		}
	}
}

void audio_play(uint32_t offset, uint32_t size)
{
	audio_struct_init(&audio_s);

	audio_s.size = size;
	audio_s.offset = offset;

	vTaskSuspendAll();
	audio_read_buffer(1);
	audio_read_buffer(0);
	xTaskResumeAll();

	HAL_TIM_Base_Start(&htim7);
	HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)audio_s.audio_data[0], audio_s.play_size[0] / 2, DAC_ALIGN_12B_R);
	
	//xSemaphoreGive(audio_s.xSemaphore);
}

void StartAudioTask(void const *argument)
{
	audio_s.xSemaphore = xSemaphoreCreateBinary();

	for (;;)
	{
		if (xSemaphoreTake(audio_s.xSemaphore, portMAX_DELAY) == pdTRUE)
		{
			vTaskSuspendAll();
			audio_read_buffer(0);
			xTaskResumeAll();
		}
	}
}

void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)
{
	static BaseType_t xHigherPriorityTaskWoken;

	audio_s.audio_flag[audio_s.now_paly_index % 2] = 0;
	audio_s.now_paly_index++;
	if (audio_s.audio_flag[audio_s.now_paly_index % 2] != 0)
	{
		HAL_DAC_Start_DMA(hdac, DAC_CHANNEL_1, (uint32_t *)audio_s.audio_data[audio_s.now_paly_index % 2], audio_s.play_size[audio_s.now_paly_index % 2] / 2, DAC_ALIGN_12B_R);
		xSemaphoreGiveFromISR(audio_s.xSemaphore, &xHigherPriorityTaskWoken);
	}
	else
	{
		audio_s.size = 0;
		HAL_TIM_Base_Stop(&htim7);
		HAL_DAC_Stop_DMA(hdac, DAC_CHANNEL_1);
		//printf("audio exit\r\n");
	}
}